var mainWrap = $(".wrap"), pop, input, statusBar, bottomArea, sendBtn,
	msgSound = document.getElementById("msgSound"), notiSound = notiTitle = notiBrowser = false;

var ws, lastActiveTime = now(), nickname = $.cookie("nickname"), uid,
	hidden, visibilityChange, visibilityState = true,
	origTitle = document.title, blink;

function now() {
	return parseInt((new Date()).getTime() / 1000);
}

function findIndex(arr, key, val) {
	for (var i=0,row; row=arr[i]; i++) {
		if (row[key] == val) {
			return i;
		}
	}
	return null;
}

/*
function sendMsg() {
	if (ws == null) {
		showStatus("与服务器连接失败,无法发送消息");
		return false;
	}

	var text = input.val();

	if ($.trim(text) == "") {
		showStatus("输入内容不可以为空或者纯空格", true);
		input.focus();
		return false;
	}

	var to = input.data("to");
	var rnd = Math.random().toString().split(".")[1];

	addMessage('rnd' + rnd, '...', nickname, text, 1);

	ws.sendProxy("send", {msg:text, to:to, rnd:rnd});

	setTimeout(function() {
		input.val("").focus();
	}, 0);
}

function buildMessageHtml(id, time, nick, content, type) {
	var className = (!type || type == 0) ? "message-receive" : "message-send";
	return '<li class="message ' + className + '" id="' + id + '">'
		+ '<div class="message-head">'
		+ '<span class="message-nick">' + nick + '</span><span class="message-time">' + time + '</span>'
		+ '</div><div class="message-content">' + content + '</div></li>';
}

function addMessage(id, time, nick, content, type) {
	var html = buildMessageHtml(id, time, nick, content, type);
	messageAppend(html, type == 1);
}
*/

function addTip(content) {
	messageAppend('<li class="tip"><span>' + content + '</span></li>');
}

function messageAppend(html, forceScroll, prepend) {
	//是否需要滚动
	var popHeight = pop.innerHeight();

	if (!forceScroll) {
		pop.stop(false, true);
		forceScroll = (pop.prop("scrollHeight") - (pop.scrollTop() + popHeight) < 50);
	}

	if (prepend) {
		pop.prepend(html);
	} else {
		pop.append(html);
	}

	var listCount = parseInt(pop.data("listCount") || 0) + 1;

	if (listCount > 200) {
		pop.find("> li").slice(0, 20).remove();
		listCount = pop.find("> li").length;
	}

	pop.data("listCount", listCount);

	if (forceScroll) {
		pop.animate({scrollTop:pop.prop("scrollHeight") - popHeight}, 250);
	}
}

function checkNickname() {
	if (nickname == "") {
		nickname = prompt("请先设置一个昵称:");

		if ($.trim(nickname) == "") {
			showStatus("必须设置一个有效的昵称才能发送消息", true);
			return false;
		}
	}
}

function getNick(nick) {
	return nick ? nick : '路人甲';
}

function showStatus(text, afterHide) {
	vm.statusText = text;

	if (afterHide) {
		//默认两秒后隐藏
		if (afterHide === true) {
			afterHide = 2000;
		}

		setTimeout(function() {
			vm.statusText = "";
		}, afterHide);
	}
}

function createConnection() {
	if (ws != null) {
		console.log("Connection is still on use, create failed!");
		return;
	}

	ws = new WebSocket("ws://" + location.hostname + ":8100/?hash=" + $("#userHash").val());
	ws.autoReconnect = true;

	var pingTimer = null;

	ws.setPing = function() {
		pingTimer = setTimeout(function() {
			var data = {type:"ping"};
			ws.send(JSON.stringify(data));
		}, 30000);
	};

	ws.clearPing = function() {
		clearTimeout(pingTimer);
	};

	ws.onopen = function(event) {
		showStatus("已建立连接", true);

		//注册名称
		if (nickname) {
			this.sendProxy("reg", {nick: nickname});
		}

		ws.setPing();
	};

	ws.onmessage = function(event) {
		var data = JSON.parse(event.data);
		MessageEvents[data.type].call(ws, data);
		ws.clearPing();
		ws.setPing();
	};

	ws.onclose = function() {
		ws.clearPing();

		if (ws.autoReconnect) {
			showStatus("连接已断开，正在重连..");
			setTimeout(createConnection, 3000)
		}

		ws = null;
	};

	ws.onerror = function(e) {
		console.log(e);
	};

	ws.sendProxy = function(type, data) {
		data.type = type;

		ws.send(JSON.stringify(data));

		ws.clearPing();
		ws.setPing();
	};
}

var MessageEvents = {
	"msg": function(data) {
		var nick = getNick(data.nick);
		var type = data.uid == uid ? 1 : 0;

		vm.addMessage('msg' + data.id, data.time, data.from, data.uid, nick, data.msg, type);

		if (type == 1) return;

		if (notiSound && msgSound.error == null) {
			msgSound.play();
		}

		if (!visibilityState) {
			if (blink == null && notiTitle) {
				var blinkState = 0;
				blink = setInterval(function () {
					if (blinkState == 0) {
						document.title = "新消息 - " + origTitle;
						blinkState = 1;
					} else {
						document.title = origTitle;
						blinkState = 0;
					}
				}, 1000);
			}

			if (notiBrowser) {
				Push.clear();
				Push.create("XChat", {
					body: nick + ": " + data.msg.substr(0, 20) + "..",
					icon: $("link[rel='shortcut icon']").attr("href"),
					timeout: 4000,
					onClick: function () {
						window.focus();
						this.close();
					}
				});
			}
		}
	},
	"send": function(data) {
		var li = $("#rnd" + data.rnd),
			msgIdx = li.data("idx"),
			chatIdx = li.parent().data("idx");

		if (data.status) {
			Vue.set(vm.chats[chatIdx].messages[msgIdx], "time", data.time);
			li.data("id", data.id);
			//li.find(".message-time").text(data.time);
		} else {
			Vue.set(vm.chats[chatIdx].messages[msgIdx], "time", '..发送失败');
			li.find(".message-time").css("color", "#F00");
			vm.chats[chatIdx].messages.push({
				tpl: "tip",
				content: data.msg
			});
			//addTip(data.msg);
		}
	},
	"user_state_change": function(data) {
		vm.onlineCount = data.num;
		
		var nick = getNick(data.nick);

		if (data.state == "online") {
			Vue.set(vm.onlineList, data.uid, nick);
		} else {
			Vue.delete(vm.onlineList, data.uid);
		}

		//if (data.uid != uid) {
		//	addTip(nick + " " + (data.state == "online" ? "进入" : "离开") + '了房间');
		//}
	},
	"online_list": function(data) {
		vm.onlineCount = data.num;
		vm.onlineList = data.onlineList;
	},
	"rename": function(data) {
		//addTip(getNick(data.oldnick) + " 改名为 " + data.newnick);
		vm.onlineList[data.uid] = data.newnick;
	},
	"pong": function() {
		lastActiveTime = now();
	},
	"baseinfo": function(data) {
		uid = data.uid;

		if (data.nickname) {
			nickname = data.nickname;
			bottomArea.find(".tool-name-reg").hide();
			
			setTimeout(function () {
				input.focus();
			}, 250);
		}

		//加载历史记录
		$.getJSON("/xchat/getHistory", function(history) {
			var html = '', type;

			for (var i=0,row; row=history[i]; i++) {
				type = row.uid != uid ? 0 : 1;
				vm.chats[0].messages.push({
					tpl: "message-item",
					id: "msg" + row.id,
					nick: row.nickname,
					time: row.time,
					type: type,
					content: row.msg
				});
				//html += buildMessageHtml('msg' + row.id, row.time, row.nickname, row.msg, type);
			}

			if (history.length > 0) {
				//html += '<li class="split"><span>以上是历史消息</span></li>';
				//messageAppend(html, true, true);
				vm.chats[0].messages.push({
					tpl: "split",
					content: "以上是历史消息"
				});

				vm.$nextTick(function() {
					var pop = $("#mbox_" + vm.chats[0].key);
					pop.scrollTop(pop.prop("scrollHeight") - pop.innerHeight());
				});
			}
		});
	},
	"reg": function(data) {
		if (data.status == "done") {
			nickname = data.nick;
			bottomArea.find(".tool-name-reg").hide();
			//onlineList.find(">li[data-uid='" + uid + "']").html(nickname);
			Vue.set(onlineList, uid, nickname);

			setTimeout(function () {
				input.focus();
			}, 250);
		} else {
			showStatus(data.msg, true);
		}
	},
	"out": function(data) {
		ws.autoReconnect = false;
		ws.close();

		switch (data.status) {
			case "close":
				location.href = "https://www.baidu.com/";
				break;
			case "replaced":
				showStatus("您已在别处登录,当前连接已断开");
				break;
			default:
				showStatus("您已被踢出");
		}
	},
	"error": function(data) {
		//addTip(data.msg);
		showStatus(data.msg, true);
	}
};

//页面可见性发生变化时触发
function onVisibilityChange(state) {
	visibilityState = state;

	if (blink != null) {
		clearInterval(blink);
		blink = null;
		document.title = origTitle;
	}
}

function adjustWindowSize() {
	var winWidth = $(window).width();
	var body = $(document.body);

	if (winWidth > 650) {
		body.removeClass("mobile");
		mainWrap.css({"height": ($(window).height() - 36) + "px", "border-radius":"5px", "margin":"18px auto"});
	} else {
		body.addClass("mobile");
		mainWrap.css({"height":"100%", "border-radius":"0px", "margin":"0 auto"});
	}
	//input.width(bottomArea.width() - 50 - 10);
}

//Vue Objects
var vm = new Vue({
	el: "#xchat",
	data: {
		onlineCount: null,
		onlineList: {},
		currentKey: "g_all",
		text: "",
		recentList: [
			{name:"全局群", key:"g_all", text:"这是一个测试.."},
			{name:"路人甲", key:"jjjjj", text:"这是一个测试.."}
		],
		chats: [{
			key: "g_all",
			inputText: "",
			messages: [{tpl: "tip", content:"Hello"}]
		}],
		lastActive: "*",
		statusText: ""
	},
	methods: {
		openChat: function(key, name, switchTo) {
			var ixRecent = findIndex(this.recentList, "key", key),
				ixChat = findIndex(this.chats, "key", key),
				currentKey;

			if (switchTo == undefined) {
				switchTo = true;
			}

			//近期列表
			if (ixRecent != null) {
				currentKey = this.recentList[ixRecent].key;
			} else {
				this.recentList.unshift({
					name: name,
					key: key,
					text: ".."
				});
				currentKey = key;
				ixRecent = 0;
			}

			//聊天框
			if (ixChat == null) {
				this.chats.push({
					key: key,
					inputText: "",
					messages: []
				});
				ixChat = this.chats.length - 1;
			}

			if (switchTo) {
				this.currentKey = currentKey;
				this.text = this.chats[ixChat].inputText;
				input.focus();
			}
		},
		sendMessage: function() {
			if (ws == null) {
				showStatus("与服务器连接失败,无法发送消息");
				return false;
			}

			if ($.trim(this.text) == "") {
				showStatus("输入内容不可以为空或者纯空格", true);
				input.focus();
				return false;
			}

			var self = this,
				to = this.currentKey,
				rnd = Math.random().toString().split(".")[1],
				i = findIndex(this.chats, "key", this.currentKey);

			this.addMessage(i, 'rnd' + rnd, '...', to, uid, nickname, this.text, 1);

			ws.sendProxy("send", {msg:this.text, to:to, rnd:rnd});

			setTimeout(function() {
				self.chats[i].inputText = self.text = "";
				input.focus();
			}, 0);
		},
		addMessage: function(idx, id, time, from, uid, nick, content, type) {
			var key = from != '' ? from : uid;

			if (this.chats.length > 200) {
				this.chats.splice(0, 20);
			}

			this.chats[idx].messages.push({
				id: id,
				tpl: "message-item",
				type: type,
				nick: nick,
				time: time,
				content: content
			});

			if (this.chats[idx].key == this.currentKey) {
				this.$nextTick(function() {
					//是否需要滚动
					var pop = $("#mbox_" + key),
						forceScroll = type == 1,
						popHeight = pop.innerHeight();

					if (!forceScroll) {
						pop.stop(false, true);
						forceScroll = (pop.prop("scrollHeight") - (pop.scrollTop() + popHeight) < 50);
					}

					if (forceScroll) {
						pop.animate({scrollTop:pop.prop("scrollHeight") - popHeight}, 250);
					}
				});
			}
		}
	},
	watch: {
		text: function(val) {
			var i = findIndex(this.chats, "key", this.currentKey);
			this.chats[i].inputText = val;
		}
	},
	created: function() {
		this.$on("current-key-change", function(key) {
			vm.currentKey = key;
		});
	},
	mounted: function() {
		$("#waitForDoc").remove();

		createConnection();
		adjustWindowSize();

		var self = this;
		pop = $("ul.chat-pop"), input = $("#sendText"), statusBar = mainWrap.find(".statusbar"),
			bottomArea = $("#bottomArea"), sendBtn = $("#sendBtn");


		//注册昵称
		if (!nickname) {
			var nameReg = bottomArea.find(".tool-name-reg");
			nameReg.find(">p").remove();
			nameReg.find("form").submit(function() {
				if ($.trim(this.mynick.value) == "") {
					showStatus("请输入有效的昵称", true);
					return false;
				}

				ws.sendProxy("reg", {nick: this.mynick.value});
				nickname = this.mynick.value;
				$.cookie("nickname", nickname, {path:location.pathname, expires:7});

				return false;
			}).show();
		}

		//sendBtn.click(sendMsg);

		//回车时发送
		input.keydown(function(e) {
			if (e.keyCode == 13) {
				return false;
			}
		}).keyup(function(e) {
			if (e.keyCode == 13) {
				self.sendMessage();
				return false;
			}
		});
	}
});

$(window).resize(adjustWindowSize);

$("#notiSetting").find(":checkbox").each(function() {
	var cookieName = $(this).attr("name"), openState;

	var cv = $.cookie(cookieName);
	if (cv !== undefined) {
		openState = cv == 1;
		$(this).prop("checked", openState);
	} else {
		openState = $(this).prop("checked");
	}

	window[cookieName] = openState;

	$(this).click(function() {
		var openState = $(this).prop("checked");
		$.cookie(cookieName, openState ? 1 : 0, {path:location.pathname, expires:7});
		window[cookieName] = openState;
	});
});

var pongViewTimer = setInterval(function() {
	vm.lastActive = now() - lastActiveTime;
}, 3500);

//Page visibility state
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
	hidden = "hidden";
	visibilityChange = "visibilitychange";
} else if (typeof document.mozHidden !== "undefined") {
	hidden = "mozHidden";
	visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
	hidden = "msHidden";
	visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
	hidden = "webkitHidden";
	visibilityChange = "webkitvisibilitychange";
}

if (document.addEventListener && typeof document[hidden] != "undefined") {
	document.addEventListener(visibilityChange, function() {
		onVisibilityChange(!document[hidden]);
	}, false);
}